package webServer

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"public.com/goutil/logUtil"
	"public.com/goutil/typeUtil"
	"public.com/goutil/zlibUtil"
)

// Api请求上下文对象
type ApiContext struct {
	// 请求对象
	request *http.Request

	// 应答写对象
	responseWriter http.ResponseWriter

	// 请求数据
	requestBytes []byte

	// 字典形式的请求数据
	requestDataByMap typeUtil.MapData
}

// 获取请求对象
// 返回值:
// *http.Request:请求对象
func (this *ApiContext) GetRequest() *http.Request {
	return this.request
}

// 获取应答写对象
// 返回值:
// *http.Response:应答写对象
func (this *ApiContext) GetResponseWriter() http.ResponseWriter {
	return this.responseWriter
}

// 获取请求字节数据
// 返回值:
// []byte:请求字节数组
func (this *ApiContext) GetRequestBytes() []byte {
	return this.requestBytes
}

// 读取内容
// r：请求对象
// isZlib:是否数据压缩
// 返回值：
// 二进制格式的内容
// 错误对象
func (this *ApiContext) readContent(isZlib bool) (content []byte, err error) {
	var buffer []byte

	defer this.request.Body.Close()
	if buffer, err = ioutil.ReadAll(this.request.Body); err != nil {
		logUtil.Log(fmt.Sprintf("url:%s,读取数据出错，错误信息为：%s", this.request.RequestURI, err), logUtil.Error, true)
		return
	}

	// 不压缩，则直接返回
	if isZlib == false {
		this.requestBytes = buffer

		return buffer, err
	}

	// 解压数据
	if content, err = zlibUtil.Decompress(buffer); err != nil {
		logUtil.Log(fmt.Sprintf("url:%s,解压缩数据出错，错误信息为：%s", this.request.RequestURI, err), logUtil.Error, true)
		return
	}

	this.requestBytes = content

	return
}

// 反序列化
// obj:反序列化结果数据
// isZlib:是否数据压缩
// 返回值:
// error:反序列化错误数据
func (this *ApiContext) Unmarshal(obj interface{}) error {
	contentData := this.GetRequestBytes()

	//反序列化
	if errMsg := json.Unmarshal(contentData, &obj); errMsg != nil {
		logUtil.Log(fmt.Sprintf("反序列化%s出错，错误信息为：%s", string(contentData), errMsg.Error()), logUtil.Error, true)
		return errMsg
	}

	return nil
}

// 获取请求的map格式数据
// 返回值:
// typeUtil.MapData:map数据
// error:错误信息
func (this *ApiContext) RequestDataByMap() (typeUtil.MapData, error) {
	if this.requestDataByMap != nil {
		return this.requestDataByMap, nil
	}

	var data typeUtil.MapData
	if err := this.Unmarshal(&data); err != nil {
		return nil, err
	}

	this.requestDataByMap = data

	return this.requestDataByMap, nil
}

// 获取请求的slice格式数据
// 返回值:
// []interface{}:返回的数组数据
func (this *ApiContext) RequestDataBySlice() []interface{} {
	result := make([]interface{}, 0, len(this.requestDataByMap))
	for _, value := range this.requestDataByMap {
		result = append(result, value)
	}
	return result
}

// 获取请求的slice格式数据
// 返回值:
// []interface{}:返回的数组数据
func (this *ApiContext) RequestDataBySlice2() ([]interface{}, error) {
	contentData := this.GetRequestBytes()

	//反序列化
	result := make([]interface{}, 0)
	if errMsg := json.Unmarshal(contentData, &result); errMsg != nil {
		logUtil.Log(fmt.Sprintf("用[]interface{}反序列化%s出错，错误信息为：%s", string(contentData), errMsg.Error()), logUtil.Error, true)
		return nil, errMsg
	}

	return result, nil
}

// 新建API上下文对象
// _request:请求对象
// _responseWriter:应答写对象
// isZlib:数据是否压缩
// 返回值:
// *ApiContext:上下文
// error:错误信息
func NewApiContext(_request *http.Request, _responseWriter http.ResponseWriter, isZlib bool) (*ApiContext, error) {
	context := &ApiContext{
		request:        _request,
		responseWriter: _responseWriter,
	}

	// 读取数据
	_, errMsg := context.readContent(isZlib)
	if errMsg != nil {
		return nil, errMsg
	}

	return context, nil
}
